﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
using System.Xml.Serialization;
using System.Threading;
using VoiceTestPlatform.Infrastrature;

namespace VoiceTestPlatform
{
    public class ProjectManager
    {
        public static event EventHandler PlayProjectDone;
        public static event EventHandler LeftPlayTimeChanged;
        public static int LeftPlayTime;
        private static IWindowsService WindowsService;
        private static string filefilter = "media files (*.mdpro)|*.mdpro";
        private static AutoResetEvent callbackEvent;
        private static ManualResetEvent pauseEvent;
        private static Timer overtime;
        private static int startIndex = 0;

        static ProjectManager()
        {
            WindowsService = new DefaultWindowsService();
            projectitems = new ObservableCollection<ProjectItem>();


            addProjectcmd = new DelegateCommand((e) =>
            {
                Sound sou = e as Sound;
                if (sou != null)
                {
                    var pi = new ProjectItem(sou);
                    pi.PlayTimes = 1;
                    pi.IsLoop = false;
                    //todo 位置
                    ProjectItems.Add(pi);
                    //var vm = new AddProjectItemViewModel(sou);
                    //WindowsService.ShowWindowByViewModel(vm);
                }

            });
            callbackEvent = new AutoResetEvent(false);
            pauseEvent = new ManualResetEvent(true);
            saveProjectCmd = new DelegateCommand(SaveProjectCommandAction);
            loadProjectCmd = new DelegateCommand(LoadProjectCommandAction);
            playProjectcmd = new DelegateCommand(PlayProjectCommandAction);
            stopPlayProjectcmd = new DelegateCommand(StopPlayProjectCommandAction);
            delProjectItemCommand = new DelegateCommand(DelProjectItemCommandAction, CanPlayAction);
        }

        private static bool CanPlayAction(object e)
        {
            return !ProjectManager.IsPlayingProject;
        }

        private static void DelProjectItemCommandAction(object obj)
        {
            if (obj == null)
            {
                return;
            }
            ProjectItems.Remove(obj as ProjectItem);
        }

        private static void StopPlayProjectCommandAction(object obj)
        {
            isStop = true;
            SoundManager.Stop();
            if (curplaying != null)
            {
                curplaying.IsPlaying = false;
                curplaying = null;
            }
        }



        private static void PlayProjectCommandAction(object obj)
        {
            if (ispause)
            {
                ispause = false;
                pauseEvent.Set();
            }
            else
            {
                if (obj == null)
                {
                    startIndex = 0;
                }
                else
                {
                    startIndex = Convert.ToInt32(obj);
                }
                BackgroundWorker bg = new BackgroundWorker();
                bg.DoWork += bg_DoWork;
                bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
                IsPlayingProject = true;
                SoundManager.PlayCommand.RaiseCanExecuteChanged();
                delProjectItemCommand.RaiseCanExecuteChanged();
                bg.RunWorkerAsync();
            }

        }

        static void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            IsPlayingProject = false;
            SoundManager.PlayCommand.RaiseCanExecuteChanged();
            delProjectItemCommand.RaiseCanExecuteChanged();
            if (PlayProjectDone != null)
            {
                PlayProjectDone(null, EventArgs.Empty);
            }
        }
        //private static SoundPlayer player;
        private static ProjectItem curplaying;
        public static bool IsPlayingProject = false;
        private static bool isStop = false;
        static void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            isStop = false;
            int loop = ParameterManager.LoopTimes;
            loop = loop < 1 ? 1 : loop;
            LeftPlayTime = loop;

            if (LeftPlayTimeChanged != null)
            {
                LeftPlayTimeChanged(null, EventArgs.Empty);
            }
            //todo 将声音播放封装
            for (int li = 0; li < loop; li++)
            {
                int curindex = 0;
                foreach (var item in ProjectItems)
                {
                    if (isStop)
                    {
                        return;
                    }

                    if (li == 0 && curindex < startIndex)
                    {
                        curindex++;
                        continue;
                    }

                    curplaying = item;
                    //if (item.IsLoop)
                    //{

                    //}
                    //else
                    //{
                    item.IsPlaying = true;
                    for (int i = 0; i < item.PlayTimes; i++)
                    {
                        int retry = 12;
                        int pt = 1;
                        while (true)
                        {

                            callbackEvent.Reset();
                            var res = new TestResult();
                            res.AudioCommand = item.AudioCommand;
                            res.AudioArea = item.AudioArea;
                            res.AudioSex = item.AudioSex;
                            res.AudioNo = item.AudioNo;
                            res.Audio = item.DisplayText;
                            res.DistanceText = ParameterManager.DistanceText;
                            res.AngelText = ParameterManager.AngelText;
                            res.NoiseText = ParameterManager.NoiseText;
                            ResultManager.PenddingResult = res;
                            Log.Write("开始播放:" + item.Path);
                            SoundManager.PlaySync(item.Path);
                           
                            res.PlayCpt = DateTime.Now;
                            if (isStop)
                            {
                                item.IsPlaying = false;
                                Log.Write("停止播放:" + item.Path);
                                return;
                            }
                            Log.Write("结否播放:" + item.Path);
                            if (!callbackEvent.WaitOne((ParameterManager.PlayDelay+ParameterManager.VoiceDelay) * 1000))
                            {
                                //超时
                                ResultManager.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
                                {
                                    if (ResultManager.PenddingResult == null)
                                    {
                                        //throw new Exception("超时时，penddingresutl 不应该为空");
                                        return;
                                    }
                                    ResultManager.PenddingResult.Result = Result.Timeout;
                                    ResultManager.PenddingResult.TestDate = DateTime.Now.ToString("yyy-MM-dd HH:mm:ss");
                                    ResultManager.ResultItems.Add(ResultManager.PenddingResult);
                                    ResultManager.PenddingResult = null;
                                }));
                            }
                            else
                            {
                                if (!ispause)
                                {
                                    Log.Write("准备播放下一个:" + item.Path);
                                    break;
                                }                               
                            }

                            pauseEvent.WaitOne();

                            if (item.AudioCommand.Trim() != Constant.Wakeupwork)//Constant.Wakeupwork)
                            {
                                Log.Write("reture1" + item.Path);
                                break;
                            }

                            if (pt < retry)
                            {
                                pt++;
                            }
                            else
                            {
                                break;
                            }

                            if (isStop)
                            {
                                item.IsPlaying = false;
                                Log.Write("reture3" + item.Path);
                                return;
                            }
                        }
                    }
                    Log.Write("reture4" + item.Path);
                    item.IsPlaying = false;
                    //}
                }
                LeftPlayTime--;
                if (LeftPlayTimeChanged != null)
                {
                    LeftPlayTimeChanged(null, EventArgs.Empty);
                }
            }


        }

        public static void SetWaitHandle()
        {
            Log.Write("SetWaitHandle--");
            callbackEvent.Set();
        }

        private static void LoadProjectCommandAction(object obj)
        {
            string[] file = WindowsService.OpenFileDialog(filefilter);
            if (file != null)
            {
                using (TextReader reader = new StreamReader(file[0]))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<ProjectItem>));
                    var result = serializer.Deserialize(reader) as ObservableCollection<ProjectItem>;
                    if (result != null)
                    {
                        ProjectItems.Clear();
                        foreach (var item in result)
                        {
                            ProjectItems.Add(item);
                        }
                    }
                }
                WindowsService.ShowMessageBox("加载流程成功");
            }
        }

        private static void SaveProjectCommandAction(object obj)
        {
            string fn = DateTime.Now.ToString("yyyyMMddHHmmss") + ".mdpro";

            Stream fs = WindowsService.SaveFileDialog(fn, filefilter);
            if (fs != null)
            {
                using (fs)
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<ProjectItem>));
                    serializer.Serialize(fs, ProjectItems);
                }
                WindowsService.ShowMessageBox("保存流程成功");
            }
        }


        private static DelegateCommand saveProjectCmd;
        //保存工程
        public static DelegateCommand SaveProjectCommand
        {
            get { return saveProjectCmd; }

        }

        private static DelegateCommand loadProjectCmd;
        //加载工程
        public static DelegateCommand LoadProjectCommand
        {
            get { return loadProjectCmd; }

        }

        private static DelegateCommand addProjectcmd;
        //添加项目

        public static DelegateCommand AddProjectCommand
        {
            get
            {
                return addProjectcmd;
            }
        }


        private static DelegateCommand playProjectcmd;
        //播放工程
        public static DelegateCommand PlayProjectCommand
        {
            get
            {
                return playProjectcmd;
            }
        }



        private static DelegateCommand stopPlayProjectcmd;
        //停止播放工程
        public static DelegateCommand StopPlayProjectCommand
        {
            get
            {
                return stopPlayProjectcmd;
            }
        }

        private static DelegateCommand delProjectItemCommand;
        //停止播放工程
        public static DelegateCommand DelProjectItemCommand
        {
            get
            {
                return delProjectItemCommand;
            }
        }

        public static void PauseProject()
        {
            ispause = true;
            pauseEvent.Reset();
            callbackEvent.Set();
        }
        private static bool ispause = false;

        public static void InsertProjectItem(int index, ProjectItem p)
        {
            //var pi = new ProjectItem(sou);
            p.PlayTimes = 1;
            p.IsLoop = false;
            //todo 位置
            ProjectItems.Insert(index, p);
        }

        private static ObservableCollection<ProjectItem> projectitems;
        [XmlElement("ItemsList")]
        public static ObservableCollection<ProjectItem> ProjectItems
        {
            get
            {
                return projectitems;
            }
        }

    }
}
